package com.mojo.elastic.controller;

import com.mojo.elastic.pojo.Bank;
import com.mojo.elastic.repository.BankRepository;
import com.mojo.response.ResultListVO;
import com.mojo.response.ResultVO;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermsQueryBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 基于bank索引的常规查询
 *
 * @author <a href="mailto:mojo_jj@163.com">Mojo</a>
 */
@RestController
@RequestMapping("/bank")
public class BankEs {
    private static final Logger logger = LoggerFactory.getLogger(BankEs.class);
    @Resource
    private BankRepository bankRepository;
    @Resource
    private ElasticsearchOperations elasticsearchOperations;

    @GetMapping("/criteria/{id}")
    public ResultVO<Bank> getById(@PathVariable Integer id) {
        // criteria 标准查询
        Criteria criteria = new Criteria("_id").is(id);
        CriteriaQuery query = new CriteriaQuery(criteria);
        SearchHit<Bank> searchHit = elasticsearchOperations.searchOne(query, Bank.class);
        return new ResultVO<>(Objects.requireNonNull(searchHit).getContent());
    }

    // region repository
    @GetMapping("/match_all")
    public ResultListVO<Bank> matchAll() {
        Iterable<Bank> all = bankRepository.findAll();
        return new ResultListVO<>(null);
    }

    @GetMapping("/{id}")
    public ResultVO<Bank> findOne(@PathVariable Integer id) {
        Bank bank = null;
        Optional<Bank> optional = bankRepository.findById(id);
        if (optional.isPresent()) {
            bank = optional.get();
        }
        return new ResultVO<>(bank);
    }

    @PostMapping("/add")
    public ResultVO<Bank> addOne() {
        Bank bank = new Bank();
        bank.setAge(11);
        bank.setAddress("成南城都汇");
        bank.setFirstname("muzhe");
        bank.setLastname("yizhi");
        bank.setEmail("muzhe@163.com");
        Bank result = bankRepository.save(bank);
        return new ResultVO<>(result);
    }
    // endregion

    @GetMapping("/term")
    public void term() {
        TermsQueryBuilder termQueryBuilder = QueryBuilders.termsQuery("firstname", "Amber");
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(termQueryBuilder);
        NativeSearchQuery query = nativeSearchQueryBuilder.build();
        SearchHits<Bank> result = elasticsearchOperations.search(query, Bank.class);
        List<SearchHit<Bank>> hitList = result.getSearchHits();
        logger.info("hit list:{}", hitList.size());
    }

    @GetMapping("match")
    public ResultListVO<Bank> match() {
        // 生成查询对象
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("address", "place");
        // QueryBuilders.boolQuery().

        // 查询条件构建器
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(matchQueryBuilder);
        nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("balance").order(SortOrder.DESC));
        nativeSearchQueryBuilder.withPageable(PageRequest.of(0, 10));
        NativeSearchQuery query = nativeSearchQueryBuilder.build();
        logger.info("query:{}", query.getQuery());
        SearchHits<Bank> hits = elasticsearchOperations.search(query, Bank.class);
        List<SearchHit<Bank>> searchHits = hits.getSearchHits();
        List<Bank> list = new ArrayList<>();
        for (SearchHit<Bank> searchHit : searchHits) {
            list.add(searchHit.getContent());
        }
        return new ResultListVO<>(list);
    }

    /**
     * scroll 实现深分页查询
     * @author Mojo
     */
    @GetMapping("scroll")
    public void scroll() {
        
    }
}
